package com.guan.poi.enums;

import com.guan.poi.exception.ExcelException;
import com.guan.poi.xml.ISymbol;
import com.guan.poi.xml.ISymbolParser;
import com.guan.poi.xml.util.XExpressionUtil;
import com.guan.poi.xml.util.XStringUtil;

/**
 * xml运算符解析
 */
public enum Symbol implements ISymbol {

    /**
     * 加法
     */
    ADD('+') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            return XExpressionUtil.add(parser.praseExpression(key.substring(0, index)), object);
        }
    },

    /**
     * 减法
     */
    SUB('-') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            if(index==0) {
                //仅仅是取负值
                Object value = parser.praseExpression(key.substring(1));
                if (value == null || !(value instanceof Number)) {
                    return null;
                }
                return -((Number) value).doubleValue();
            }
            return super.prase(parser, key, index);
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            return XExpressionUtil.sub(parser.praseExpression(key.substring(0, index)), object);
        }
    },

    /**
     * 乘法
     */
    MUL('*') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            return XExpressionUtil.mul(parser.praseExpression(key.substring(0, index)), object);
        }
    },

    /**
     * 除法
     */
    DIV('/') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            return XExpressionUtil.div(parser.praseExpression(key.substring(0, index)), object);
        }
    },

    /**
     * 取余
     */
    MOD('%') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            return XExpressionUtil.mod(parser.praseExpression(key.substring(0, index)), object);
        }
    },


    /**
     * 等号
     */
    EQ('=') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            char c1 = key.charAt(index - 1);
            if ('=' == c1) {
                return prase(parser, key, index - 1, object);
            }
            if ('!' == c1) {
                return NEQ.prase(parser, key, index - 1, object);
            }
            if ('>' == c1) {
                return GTE.prase(parser, key, index - 1, object);
            }
            if ('<' == c1) {
                return LTE.prase(parser, key, index - 1, object);
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if (object == null && o == null) {
                return true;
            }
            return !(object == null || o == null) && object.equals(o);
        }
    },

    /**
     * 大于
     */
    GT('>') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            if(object==null || !(object instanceof Number)) {
                return true;
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if(o==null || !(o instanceof Number)) {
                return false;
            }
            return ((Number) o).doubleValue() > ((Number) object).doubleValue();
        }
    },

    /**
     * 小于
     */
    LT('<') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            if(object==null || !(object instanceof Number)) {
                return false;
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if(o==null || !(o instanceof Number)) {
                return true;
            }
            return ((Number) o).doubleValue() < ((Number) object).doubleValue();
        }
    },

    /**
     * 大于等于
     */
    GTE('≥') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            return prase(parser, key, index, parser.praseExpression(key.substring(index+2)));
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            if(object==null || !(object instanceof Number)) {
                return true;
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if(o==null || !(o instanceof Number)) {
                return false;
            }
            return ((Number) o).doubleValue() >= ((Number) object).doubleValue();
        }
    },

    /**
     * 小于等于
     */
    LTE('≤') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            return prase(parser, key, index, parser.praseExpression(key.substring(index+2)));
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            if(object==null || !(object instanceof Number)) {
                return false;
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if(o==null || !(o instanceof Number)) {
                return true;
            }
            return ((Number) o).doubleValue() <= ((Number) object).doubleValue();
        }
    },

    /**
     * 括号
     */
    PARENTHESIS(')') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            int startIndex = XStringUtil.getParenthesesStart(key, index);
            if (startIndex <= 0) {
                return parser.praseExpression(key.substring(startIndex+1, index));
            }

            String prev = key.substring(0, startIndex);

            // 前边是表达式
            int prevIndex = XStringUtil.lastIndexOfAny(prev, EXPRESSION_MID);
            if(prevIndex>-1) {
                // 先算括号
                Symbol symbol = Symbol.create(key.charAt(prevIndex));
                Object object  = symbol.prase(parser, prev, prevIndex, parser.praseExpression(key.substring(startIndex + 1, index).trim()));
                if(index<key.length()-1) {
                    return parser.getProperty(object, key.substring(index+1));
                }
                return object;
            }


            // 大写,静态方法
            if(Character.isUpperCase(key.charAt(0))) {
                return parser.invokeStaticMothod(key);
            }

            if(key.startsWith("static.")) {
                return parser.invokeStaticMothod(key.substring("static.".length()));
            }

            // 方法,前边是点
            int spotIndexB = prev.lastIndexOf(SPOT);
            if(spotIndexB<=0) {
                throw new ExcelException("表达式错误:["+key+"]");
            }
            //获取对象
            Object valueB = parser.praseExpression(prev.substring(0, spotIndexB).trim());
            if(valueB==null) {
                return null;
            }
            //获取对象方法
            return parser.getProperty(valueB, key.substring(spotIndexB + 1).trim());
        }
    },

    /**
     * 二进制
     */
    VERTICAL('|') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            char c1 = key.charAt(index-1);
            if('|' == c1) {
                return OR.prase(parser, key, index-1, object);
            }

            if(object==null || !(object instanceof Number)) {
                return null;
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if(o==null || !(o instanceof Number)) {
                return null;
            }
            return ((Number) object).intValue() | ((Number) o).intValue();
        }
    },

    /**
     * 或
     */
    OR('‖') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            return prase(parser, key, index, parser.praseExpression(key.substring(index+2)));
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            Boolean o = XExpressionUtil.getBoolean(parser.praseExpression(key.substring(0, index-1)));
            if(o) {
                return true;
            }
            return XExpressionUtil.getBoolean(object);
        }
    },

    /**
     * 二进制
     */
    WITH('&') {

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            if('&' == key.charAt(index-1)) {
                return AND.prase(parser, key, index-1, object);
            }
            if(object==null || !(object instanceof Number)) {
                return null;
            }
            Object o = parser.praseExpression(key.substring(0, index));
            if(o==null || !(o instanceof Number)) {
                return null;
            }
            return ((Number) object).intValue() & ((Number) o).intValue();
        }
    },

    /**
     * 且
     */
    AND('§') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            return prase(parser, key, index, parser.praseExpression(key.substring(index+2)));
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            Boolean o = XExpressionUtil.getBoolean(parser.praseExpression(key.substring(0, index-1)));
            if(!o) {
                return false;
            }
            return XExpressionUtil.getBoolean(object);
        }
    },

    /**
     * 二进制
     */
    TILDE('~') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            if(object==null || !(object instanceof Number)) {
                return null;
            }
            return ~((Number) object).intValue();
        }
    },

    QUESTION('?') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            if(index==0) {
                return null;
            }
            // 前面是括号
            String prev = key.substring(0, index).trim();
            if(prev.charAt(prev.length()-1)==')') {
                int start = XStringUtil.getParenthesesStart(prev, prev.length() - 1);
                Object valueE = parser.praseExpression(prev.substring(start + 1, prev.length()-1));
                if(start<0) {
                    return prase(parser, key, index, valueE);
                }
                return Symbol.prase(parser, prev.substring(0, start), prase(parser, key, index, valueE));
            }

            // 前面是表达式
            int indexMid = XStringUtil.lastIndexOfAny(prev, EXPRESSION_MID);
            if(indexMid<0) {
                return prase(parser, key, index, parser.praseExpression(prev));
            }

            Symbol symbol = Symbol.create(key.charAt(indexMid));
            return prase(parser, key, indexMid, symbol.prase(parser, prev, indexMid, parser.praseExpression(prev.substring(indexMid + 1))));
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            int indexA = key.lastIndexOf(":");
            if (indexA<0) {
                return null;
            }
            Boolean bObject = XExpressionUtil.getBoolean(object);
            if(bObject) {
                return parser.praseExpression(key.substring(key.indexOf("?")+1, indexA));
            }
            return parser.praseExpression(key.substring(indexA + 1));
        }
    },

    /**
     * 取反
     */
    NOT('!') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            return!XExpressionUtil.getBoolean(object);
        }
    },

    /**
     * 不等于
     */
    NEQ('≠') {
        @Override
        public Object prase(ISymbolParser parser, String key, int index) {
            return prase(parser, key, index, parser.praseExpression(key.substring(index+2)));
        }

        @Override
        public Object prase(ISymbolParser parser, String key, int index, Object object) {
            Object eq = EQ.prase(parser, key, index, object);
            return !XExpressionUtil.getBoolean(eq);
        }
    },

    ;

    private char symbol;

    Symbol(char symbol) {
        this.symbol = symbol;
    }

    public char getSymbol() {
        return symbol;
    }

    public static Symbol create(char symbol) {
        for (Symbol item : Symbol.values()) {
            if(symbol==item.symbol) {
                return item;
            }
        }
        throw new RuntimeException("表达式错误");
    }

    public static Object prase(ISymbolParser parser, String key, Object object) {
        int index = XStringUtil.lastIndexOfAny(key, EXPRESSION_MID);
        if(index<0) {
            return object;
        }
        Symbol symbol = Symbol.create(key.charAt(index));
        return symbol.prase(parser, key, index, object);
    }
}
